package rainy.file.synchronization.client;

import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import rainy.file.synchronization.client.channel.ChannelFactory;
import rainy.file.synchronization.client.file.FileTailer;
import rainy.file.synchronization.client.file.FileTailerListener;
import rainy.file.synchronization.config.RainyRunTime;
import rainy.file.synchronization.log.MDC;

/**
 * 发送格式为 COMMAND#FILENAME#CONTENT
 * 
 * @author Grom
 *
 */
public class FileTailerSendClient {

	private String host = RainyRunTime.getStringPropDefine("rainy.master.serverName", "localhost");
	private int port = RainyRunTime.getIntegerPropDefine("rainy.master.port", 9054);
	private static BlockingQueue<String> tailedInfoQueue = new LinkedBlockingDeque<>();
	private static final Object key = new Object();
	private static final String clientType = "tailSender";

	static {
		MDC.gPush("type", "TAIL");
	}

	public FileTailerSendClient() {

	}

	public FileTailerSendClient(String host, int port) {
		this.host = host;
		this.port = port;
	}

	public static void addNewAddedContent(String content) {
		synchronized (key) {
			tailedInfoQueue.add(content);
		}
	}

	public void run() throws Exception {
		trigerLocalFileMonitor();
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			// init channel while start!
			Channel channel = ChannelFactory.getCurrentChannel(clientType, group);
			System.out.println("[ tail ] Client is started to connect [" + host + ":" + port + "]");
			System.out.println("[ tail ] Monitor is started!");
			boolean exit = false;
			while (true && !exit) {
				String line = tailedInfoQueue.take();
				System.out.println("Start to send tail : " + line);
				String sendStr = RainyRunTime.COMMOND_TAIL + RainyRunTime.COMMAND_CONTENT_SPLIT + line;
				channel = ChannelFactory.getCurrentChannel(clientType, group);
				channel.writeAndFlush(sendStr + "\r\n");
			}
		} finally {
			group.shutdownGracefully();
		}
	}

	private void trigerLocalFileMonitor() {
		String localFile = RainyRunTime.getPropDefine("rainy.slaves.tail.target.file");
		File file = new File(localFile);
		if (file.isDirectory()) {
			file.listFiles(new FileFilter() {
				public boolean accept(File pathname) {
					if (pathname.isDirectory()) {
						return false;
					}
					FileTailer tailer = new FileTailer(pathname);
					tailer.addLogFileTailerListener(new FileTailerListener());
					tailer.start();
					return false;
				}
			});
		} else {
			FileTailer tailer = new FileTailer(file);
			tailer.addLogFileTailerListener(new FileTailerListener());
			tailer.start();
		}
	}

	public static void main(String[] args) throws Exception {
		new FileTailerSendClient().run();
	}
}